<script setup>
  import { useDynamicForm } from '@/hooks'
  import { ElMessage } from 'element-plus'
  import { ref, watch, computed, useTemplateRef, nextTick } from 'vue'

  const formRef = useTemplateRef('formRef')

  /* props */
  const { visible, options } = useDynamicForm()

  /* 表单数据 */
  const formData = ref({})
  const loading = ref(false)
  const title = computed(() => options.value.title)
  const width = computed(() => options.value.width ?? 420)
  const fields = computed(() => options.value.fields || [])

  /* 打开弹窗时初始化默认值，关闭时清空 */
  watch(
    () => visible.value,
    val => {
      if (val) {
        nextTick(() => {
          formRef.value.resetFields()
          nextTick(() => {
            formData.value = fields.value.reduce((acc, field) => {
              if (typeof field.default === 'function') {
                acc[field.key] = field.default()
              } else {
                acc[field.key] = field.default ?? ''
              }
              return acc
            }, {})
          })
        })
      }
    }
  )

  function onCancel() {
    visible.value = false
  }

  function onClose() {
    console.log('关闭')
    loading.value = false
    formData.value = {}
  }

  function onSubmit() {
    const close = () => onCancel()

    const setLoading = val => (loading.value = val)

    nextTick(() => {
      formRef.value.validate(valid => {
        if (valid) {
          console.log('校验成功')
          console.log(formData.value)
          options.value.onConfirm({ ...formData.value }, { close, setLoading })
        } else {
          console.error('校验失败')

          ElMessage.warning('请检查输入项')
        }
      })
    })
  }
</script>

<template>
  <el-dialog
    v-model="visible"
    :title="title"
    :width="width"
    append-to-body
    center
    :close-on-click-modal="false"
    @closed="onClose"
  >
    <el-form :model="formData" label-width="150px" label-position="left" ref="formRef">
      <el-form-item
        v-for="(field, idx) in fields"
        :key="idx"
        :label="field.label"
        :prop="field.key"
        :required="field.required"
      >
        <!-- 输入框 -->
        <el-input
          v-if="field.type === 'input' || !field.type"
          v-model="formData[field.key]"
          :placeholder="field.placeholder || `请输入${field.label}`"
        />
        <!-- 数字 -->
        <el-input-number
          v-else-if="field.type === 'number'"
          v-model="formData[field.key]"
          style="width: 100%"
          :min="field.min"
          :max="field.max"
        />
        <!-- 选择框 -->
        <el-select
          v-else-if="field.type === 'select'"
          v-model="formData[field.key]"
          :placeholder="field.placeholder || `请选择${field.label}`"
          style="width: 100%"
          @change="field.onChange"
        >
          <el-option v-for="item in field.options" :key="item.value" :label="item.label" :value="item.value" />
        </el-select>
        <!-- 开关 -->
        <el-switch v-else-if="field.type === 'switch'" v-model="formData[field.key]" />
        <!-- 时间选择 -->
        <el-time-select
          v-else-if="field.type === 'time-select'"
          v-model="formData[field.key]"
          style="width: 100%"
          start="07:00"
          step="00:30"
          end="23:00"
          placeholder="请选择时间"
        />
        <!-- 日期时间选择 -->
        <el-date-picker
          v-else-if="field.type === 'datetime'"
          v-model="formData[field.key]"
          type="datetime"
          placeholder="请选择日期时间"
          style="width: 100%"
        />
        <!-- 级联选择器 -->
        <el-cascader
          v-else-if="field.type === 'cascader'"
          v-model="formData[field.key]"
          v-bind="field"
          :options="field.options"
          @change="field.onChange"
        />
      </el-form-item>
    </el-form>

    <template #footer>
      <div class="dialog-footer">
        <el-button @click="onCancel">取消</el-button>
        <el-button type="primary" @click="onSubmit" :loading="loading"> 确认 </el-button>
      </div>
    </template>
  </el-dialog>
</template>

<style scoped lang="less"></style>
